﻿using CocoaAni.Net.WebSockets.Exceptions;
using CocoaAni.Net.WebSockets.Messages;
using CocoaAni.Net.WebSockets.Server.Controllers;
using CocoaAni.Net.WebSockets.Server.DefineInfos;
using CocoaAni.Net.WebSockets.Tools;
using Newtonsoft.Json.Linq;
using System.Net.Sockets;
using CocoaAni.Net.WebSockets.Frames;
using CocoaAni.Net.WebSockets.Server.ArgAdapters.Base;
using CocoaAni.Net.WebSockets.Server.Exceptions;
using MessageHandlerAttribute = CocoaAni.Net.WebSockets.Server.Attributes.MessageHandlerAttribute;

namespace CocoaAni.Net.WebSockets.Server;

public class WebSocketContext
{
    public string ControllerAndHandlerPath => ControllerInfo!=null! && MessageHandlerInfo!=null!? $" On=>[{ControllerInfo.MapPath}].[{MessageHandlerInfo.Name}]":string.Empty;
    public IWebSocketServiceDispatcher Dispatcher { get;protected set; }
    public MessageArgContext MessageArgContext { get;protected set; }
    public CancellationTokenSource CancellationTokenSource { get; protected set; }

    public int ClientId { get; set; }
    public WebSocket Socket { get; protected internal set; }
    public ControllerInfo ControllerInfo { get; protected internal set; }
    public WSHandShakeRequest HandShakeRequest { get; protected internal set; }
    public Message Message { get; protected internal set; }
    public bool IsSending { get; protected internal set; } = false;
    public Queue<object> SendQueue { get; set; }
    public Task ReceiveTaskWorker { get; protected internal set; } = Task.CompletedTask;
    public HandlerDefineInfo MessageHandlerInfo { get; set; }
    public ReceiveBuffer MessageReceiveBuffer { get; set; }
    public Task DispatcherTask { get; set; }

    public WebSocketContext(int clientId, WebSocket socket,IWebSocketServiceDispatcher dispatcher)
    {
        ClientId = clientId;
        Socket = socket;
        Dispatcher= dispatcher;
        Message = null!;
        HandShakeRequest = null!;
        ControllerInfo = null!;
        SendQueue = new Queue<object>();
        MessageHandlerInfo = null!;
        MessageReceiveBuffer = null!;
        MessageArgContext = new MessageArgContext(this);
        CancellationTokenSource=new CancellationTokenSource();
    }

   

    public void SwitchController(string name, string? handlerName = null)
    {
        var controllerName = name.Replace("Controller", "");
        if (!Dispatcher.ControllerInfos.ContainsKey(controllerName))
        {
            throw new WebSocketException($"Controller {name} Not Found");
        }
        ControllerInfo = Dispatcher.ControllerInfos[controllerName];
        SwitchMessageHandler(handlerName??MessageHandlerAttribute.Default);
    }
    public void SwitchController<T>()
        where T : WebSocketController
    {
        SwitchController(typeof(T).Name);
    }
    public void SwitchMessageHandler(string name)
    {
        if (!ControllerInfo.HandlerInfos!.ContainsKey(name!))
        {
            throw new WebSocketException($"On ControllerInfo {ControllerInfo.MapPath} Not Found Handler {name}");
        }
        MessageHandlerInfo= ControllerInfo.HandlerInfos[name];
    }
    public void SendMessage(object message)
    {
        Dispatcher.SendMessage(this, message, CancellationTokenSource.Token);
    }

    public async Task<Message> ReceiveMessageAsync(CancellationToken cancellationToken=default)
    {
        var message = await Socket.ReceiveAsync(MessageReceiveBuffer, cancellationToken);
        MessageReceiveBuffer.Reset();
        return message;
    }
}